/* Deterministic Algorithms
*
*
*/

#include "sudoku.h"

bool determine(Grid gIn,Grid g){

	bool progress = TRUE;
	int x, y, s, num;
	
	memcpy(g, gIn, sizeof(cell) * 81);


	while (progress){
        //printf("Determining....\n");
                progress = FALSE;
                s = 0;
                for (y = 0; y < GRID_SIZE; y++){
                        for (x = 0; x < GRID_SIZE; x++){
				num = bitCount(gridIndex(g,x,y));
                                if(num>1){
                                        //printf("Cell=%d:%d\n",x,y);
                                        s = onlyInColumn(g,x,y);
                                        if (s > 0){
                                                //printf("Setting Cell to %d\n",s);
                                                setCell(s, &gridIndex(g,x,y));
                                                //prtCell(gridIndex(g,x,y), 1);
                                                progress |= unmarkCells(g, x, y);
                                                break;
                                        }
                                        s = onlyInRow(g,x,y);
                                        if (s > 0){
                                                setCell(s, &gridIndex(g,x,y));
                                                //printf("Setting Cell to %d\n",s);
                                                //prtCell(gridIndex(g,x,y),1);
                                                progress |= unmarkCells(g, x, y);
                                                break;
                                        }
                                        s = onlyInSquare(g,x,y);
                                        if(s > 0){
                                                setCell(s, &gridIndex(g,x,y));
                                                progress |= unmarkCells(g, x, y);
                                                break;
                                        }
                                }
                        }
                        if(progress){
                                break;
                        }
                }
        }


	return isGridSolved (g);
}

int onlyInColumn(Grid g, int x, int y){
	
	cell mask = 0x1;
	cell test;
	int i, j, sum;
	//printf("Only Column Test\n");
	for(i = 1; i <= GRID_SIZE; i++){
		mask = mask << (i-1);
		test = mask & gridIndex(g,x,y);
		//printf("cell:");
		//prtCell(mask,0);
		//printf("\ntest:");
		//prtCell(test,0);
		//printf("\n");
		if(bitCount(test) == 1){
			//printf("Bit test passed\n");
			for (j = 0; j < GRID_SIZE; j++){
				if(j != y){
					test = mask & gridIndex(g,x,j);
					//printf("Column Test %d against %d, Result:",j,y);
					//prtCell(test,0);
					//printf("\n");
					sum = sum + bitCount(test);
				}
			}
			if(sum == 0){
				//printf("Column Check, Found Value\n");
				return i;
			}
		}
		sum = 0;
		mask = 0x1;
	}

	//printf("Column Check, Nothing Found\n");
	return 0;

}

int onlyInRow(Grid g, int x, int y){

	cell mask = 0x1;
	cell test;
	int i, j, sum;

	for(i = 1; i <= GRID_SIZE; i++){
		mask = mask << (i-1);
		test = mask & gridIndex(g,x,y);
		if(bitCount(test) == 1){
			for (j = 0; j < GRID_SIZE; j++){
				if(j != x){
					test = mask & gridIndex(g,j,y);
					sum = sum + bitCount(test);
				}
			}
			if(sum == 0){
				//printf("Row Check, Found Value\n");
				return i;
			}
		}
	sum = 0;
	mask = 0x1;
	}
	
	//printf("Row Check, Nothing Found\n");	
	return 0;

}

int onlyInSquare(Grid g, int x, int y){
	
	cell mask = 0x1;
	cell test;
	int sx, sy, sum, i, xi, yi;
	sx = getSubGridX(x);
	sy = getSubGridY(y);

	for(i = 1; i <= GRID_SIZE; i++){
		mask = mask << (i-1);
		test = mask & gridIndex(g,x,y);
		if(bitCount(test) == 1){
			for (yi = 0; yi < SUB_GRID_SIZE; yi++){
				for (xi = 0; xi < SUB_GRID_SIZE; xi++){
					if (&gridIndex(g, x, y) != &subGridIndex(g, sx, sy, xi, yi)){ // Diff Cells
						test = mask & subGridIndex(g, sx, sy, xi, yi);
						sum = sum + bitCount(test);
					}
				}
			}
			/*if(x == 5 && y == 6){
				prtCell(gridIndex(g, x, y), 2);
				printf(" Cell (6,7) Testing %d, Result:%d\n", i, sum);
			}*/
			if(sum == 0){
				//printf("Square Check, Found Value\n");
				return i;
			}
		}
	sum = 0;
	mask = 0x1;
	}

	//printf("Square Check, Nothing Found\n");
	return 0;
}



